XM.lang.namespace('XM.canvas');
/**
 * 事件转换器
 */
XM.canvas.EventTranslator = {
    /**
     * 被监听的canvas
     * @private
     */
    _canvas: null,
    set canvas(c) {
        this._canvas = c;

        this._canvas.onlick =
        this._canvas.ondbclick =
        this._canvas.onmousemove =
        this._canvas.onmousedown =
        this._canvas.onmouseup = function (ev) {
            XM.canvas.EventTranslator.transformEvent(ev);
        };
    },
    get canvas() {
        return this._canvas;
    },

    /**
     * 鼠标是否按下
     * @type {boolean}
     */
    isMouseDown: false,
    /**
     * 鼠标上移
     * @type {boolean}
     */
    isMouseOver: false,
    /**
     * 是否正拖动
     * @type {boolean}
     */
    isDragging: false,
    /**
     * 鼠标按下时的事件快照
     * @type {object}
     */
    mouseDownEvent: null,

    /**
     * 默认都是事件发生完之后触发
     * 事件的上下文都是Item对象
     *
     * @private
     */
    eventStack: {
        'click':(function(){var a = []; a.eventType = 'click'; return a;})(), // 单击
        'drag':(function(){var a = []; a.eventType = 'drag'; return a;})(), // 拖动
        'drop':(function(){var a = []; a.eventType = 'drop'; return a;})(), // 释放
        'hit':(function(){var a = []; a.eventType = 'hit'; return a;})(), // 碰撞 需要传入被碰撞对象列表
        'leave':(function(){var a = []; a.eventType = 'leave'; return a;})(), // 碰撞后离开
        'move':(function(){var a = []; a.eventType = 'move'; return a;})(), // 位移
        'paint':(function(){var a = []; a.eventType = 'paint'; return a;})(), // 绘制
        'clear':(function(){var a = []; a.eventType = 'clear'; return a;})(), // 清除绘制
        'mouseOver':(function(){var a = []; a.eventType = 'mouseOver'; return a;})(), // 鼠标上移
        'mouseOut':(function(){var a = []; a.eventType = 'mouseOut'; return a;})(), // 鼠标移出
        'mouseMove':(function(){var a = []; a.eventType = 'mouseMove'; return a;})(), // 鼠标滑动
        'mouseDown':(function(){var a = []; a.eventType = 'mouseDown'; return a;})() // 鼠标按下
    },

    /**
     * 绑定事件
     *
     * 同一类型的事件可以绑定多个回调方法
     * 触发回调的顺序与绑定顺序一致
     * 这里对item注入了eventList属性
     *
     * @public
     * @param item {XM.canvas.Item}
     * @param type
     * @param callback
     */
    bindEvent: function (item, type, callback) {
        //item.eventList = item.eventList instanceof Object ? item.eventList : {};
        item.eventList[type] = callback;

        this.eventStack[type].push(item);
    },

    /**
     * 已被支持的从canvas处传递进来的事件类型列表
     * @private
     */
    supportedInputEventType: [
        'click',
        'dbclick',
        'mousemove',
        'mousedown',
        'mouseup'
    ],

    /**
     * 事件转换
     * @public
     * @param ev
     */
    transformEvent: function (ev) {
        var eStack = new Array();

        if (XM.lang.contain(ev.type, this.supportedInputEventType)) {
            switch (ev.type) {
                case 'click':
                    // TODO:click event invoke
                    eStack = this.eventStack['click'];
                break;
                case 'mousemove':
                    if (!this.isDragging && this.isMouseDown &&
                            (Math.abs(ev.clientX - this.mouseDownEvent.clientX) > GLOBAL_CONFIG['global'].dragOffset ||
                                    Math.abs(ev.clientY - this.mouseDownEvent.clientY) > GLOBAL_CONFIG['global'].dragOffset)) {
                        // TODO:drag event invoke
                        this.isDragging = true;
                        eStack = this.eventStack['drag'];
                    } else {
                        // TODO: mouseMove event invoke
                        eStack = this.eventStack['mouseMove'];
                    }
                break;
                case 'mousedown':
                    this.mouseDownEvent = {clientX: ev.clientX, clientY: ev.clientY};
                    this.isMouseDown = true;

                    // TODO:mouseDown event invoke
                    eStack = this.eventStack['mouseDown'];
                break;
                case 'mouseup':
                    if (this.isDragging) {
                        // TODO:drop event invoke
                        eStack = this.eventStack['drop'];
                    } else {
                        // TODO:mouseUp event invoke
                        eStack = this.eventStack['click'];
                    }

                    this.isMouseDown = false;
                    this.isDragging = false;
                    this.mouseDownEvent = null;
                break;
            }
        }

        this.trigger(eStack, ev);
    },

    /**
     * 触发事件
     * @param stack
     * @param ev
     */
    trigger: function (stack, ev) {
        for (var i = 0, len = stack.length; i < len; i++) {
            var item = stack[i];
            if (item.inScope(ev.clientX, ev.clientY)) {
                if (!item.isMouseOver && item.eventList.mouseOver && ev.type === 'mousemove') {
                    this.triggerItem(item, 'mouseOver', ev);
                }
                item.isMouseOver = true;
                this.triggerItem(item, stack.eventType, ev);
            } else if (item.isMouseOver &&
                        ev.type === 'mousemove' &&
                        item.eventList.mouseOut) {
                // TODO: mouseOut event invoke
                item.isMouseOver = false;
                if (item.eventList.mouseOut) {
                    this.triggerItem(item, 'mouseOut', ev);
                }
            }
        }
    },

    /**
     * 触发事件
     * @param item {GemUnit}
     * @param type {string}
     * @param ev {MouseEvent}
     */
    triggerItem: function (item, type, ev) {
        item.eventList[type].call(item, ev);
    },

    /**
     * 此方法需要被注射到item中用于判断是否在自己范围内
     * @param x {number}
     * @param y {number}
     */
    _inScope: function (x, y) {
        return (x > this.x && x < this.x + this.width &&
                y > this.y && y < this.y + this.height);
    },

    /**
     * 解析对象中的事件并注册
     * @param item
     */
    parseItems: function (items) {
        if (items instanceof Array) {
            for (var i = 0, len = items.length; i < len; i++) {
                this.parseItems(items[i]);
            }
        } else if (items instanceof Object && items.name) {
            var item = items;
            item.image = XM.common.ResourceManager.getResource(item.resourceID);
            if (item.eventList) {
                for (var p in item.eventList) {
                    if (p in this.eventStack) {
                        this.bindEvent(item, p, item.eventList[p]);
                    };
                }
            }
            // 属性注射
            this.inject(item);
            if (item.items instanceof Array) this.parseItems(item.items);
        }
    },

    inject: function (item) {
        item.inScope = this._inScope;
        item.isMouseOver = false;

        // 给没有mouseMove事件的加一个空的事件，以便触发mouseOver和mouseOut
        if (item.eventList && !item.eventList.mouseMove) {
            item.eventList.mouseMove = function (ev) {};
            this.bindEvent(item, 'mouseMove', function (ev) {});
        }
    }
};